package cn.lili.modules.payment.kit.plugin.wsrcom;

import cn.lili.common.enums.ResultUtil;
import cn.lili.common.properties.ApiProperties;
import cn.lili.common.utils.IpUtils;
import cn.lili.common.utils.SnowFlake;
import cn.lili.common.vo.ResultMessage;
import cn.lili.modules.payment.entity.RefundLog;
import cn.lili.modules.payment.entity.enums.PaymentMethodEnum;
import cn.lili.modules.payment.kit.CashierSupport;
import cn.lili.modules.payment.kit.Payment;
import cn.lili.modules.payment.kit.dto.PayParam;
import cn.lili.modules.payment.kit.params.dto.CashierParam;
import cn.lili.modules.payment.service.PaymentService;
import cn.lili.modules.payment.service.RefundLogService;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.jfinal.kit.HttpKit;
import com.jfinal.kit.Kv;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

@Slf4j
@Component
@SuppressWarnings({"unchecked", "rawtypes"})
public class WsrcomPlugin implements Payment {
    private static final String GATEWAY_URL = "https://openapi.minda-group.com";
    private static final String OPEN_USER_ID = "10002379135024";
    private static final String KEY = "F3E923F4C8400F34202F71D5FCDFC580";

    /**
     * 支付日志
     */
    @Autowired
    private PaymentService paymentService;
    /**
     * 退款日志
     */
    @Autowired
    private RefundLogService refundLogService;
    /**
     * 收银台
     */
    @Autowired
    private CashierSupport cashierSupport;
    /**
     * API域名
     */
    @Autowired
    private ApiProperties apiProperties;

    private String getRequestBody(Kv requestBody) {
        StringBuilder json = new StringBuilder();
        List<String> bodyKeys = new ArrayList<>(requestBody.keySet());
        Collections.sort(bodyKeys);
        for (String key : bodyKeys) {
            json.append("\"").append(key).append("\":\"").append(requestBody.getStr(key)).append("\",");
        }
        json.deleteCharAt(json.length() - 1);
        json.insert(0, "{").append("}");
        return json.toString();
    }

    private String sign(Kv params) {
        List<String> keys = new ArrayList<>(params.keySet());
        Collections.sort(keys);
        StringBuilder paramUrl = new StringBuilder();
        for (String key : keys) {
            paramUrl.append(key).append("=").append(params.get(key)).append("&");
        }
        paramUrl.deleteCharAt(paramUrl.length() - 1);
        return DigestUtils.md5Hex(paramUrl + KEY);
    }

    @SneakyThrows
    private ResultMessage<Object> pay(String channelType, HttpServletRequest request, HttpServletResponse response, PayParam payParam) {
        CashierParam cashierParam = cashierSupport.cashierParam(payParam);
        //请求订单编号
        String outTradeNo = SnowFlake.getIdStr();
        //准备支付参数

        Kv params = Kv.create();
        params.set("open_userid", OPEN_USER_ID);
        params.set("res_body", getRequestBody(
                Kv.create()
                        .set("sub_mch_id", "6015667111783")
                        .set("channel_type", channelType)
                        .set("total_fee", cashierParam.getPrice() + "")
                        .set("pay_name", URLEncoder.encode("商品", "utf-8"))
                        .set("pay_body", URLEncoder.encode("商品", "utf-8"))
                        .set("notify_url", notifyUrl(apiProperties.getBuyer(), PaymentMethodEnum.WSRCOM).replaceAll("/", "\\/"))
                        .set("out_trade_no", outTradeNo)
                        .set("user_ip", IpUtils.getIpAddress(request))
                        .set("server_url", "h5.hnguanpei.cn")
        ));
        params.set("service", "gateway.unified.pay");
        params.set("sign_type", "MD5");

        params.set("sign", sign(params));

        String responseText = HttpKit.post(GATEWAY_URL, params, null);
        log.info("{}", responseText);
        JSONObject obj = JSON.parseObject(responseText);
        String respCode = obj.getString("rsp_code");
        String respMsg = obj.getString("rsp_msg");
        if ("0000".equals(respCode)) {
            String payUrl = obj.getJSONObject("request_array").getString("payUrl");
            return ResultUtil.data(payUrl);
        } else {
            return ResultUtil.error(-1, "支付失败");
        }
    }

    @Override
    public ResultMessage<Object> h5pay(HttpServletRequest request, HttpServletResponse response, PayParam payParam) {
        String type = request.getParameter("type");
        return pay(type, request, response, payParam);
    }

    @Override
    public ResultMessage<Object> jsApiPay(HttpServletRequest request, PayParam payParam) {
        return null;
    }

    @Override
    public ResultMessage<Object> appPay(HttpServletRequest request, PayParam payParam) {
        return null;
    }

    @Override
    public ResultMessage<Object> nativePay(HttpServletRequest request, PayParam payParam) {
        String type = request.getParameter("type");
        return pay(type, request, null, payParam);
    }

    @Override
    public ResultMessage<Object> mpPay(HttpServletRequest request, PayParam payParam) {
        return null;
    }

    @Override
    public void refund(RefundLog refundLog) {

    }

    @Override
    public void callBack(HttpServletRequest request) {

    }

    @Override
    public void notify(HttpServletRequest request) {

    }

    @Override
    public void refundNotify(HttpServletRequest request) {

    }

    @Override
    public String callbackUrl(String api, PaymentMethodEnum paymentMethodEnum) {
        return null;
    }

    @Override
    public String notifyUrl(String api, PaymentMethodEnum paymentMethodEnum) {
        return null;
    }

    @Override
    public String refundNotifyUrl(String api, PaymentMethodEnum paymentMethodEnum) {
        return null;
    }
}
